﻿using System;

using BizElements.BusinessLayer;

namespace BizElements.Web
{
    /// <summary>
    /// Data and meta required to bind a business field to a <see cref="IBoundControl"/> control.
    /// </summary>
    [Serializable]
    public sealed class BindableField : IBindableField
    {
        #region Constructors.

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.</param>
        public BindableField(string bindingName, Type dataType, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            this.DataType = dataType;
            this.SatelliteFields = satelliteFields;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="isReadOnly">Indicates whether the contents of the field may be modified by binding engines.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.</param>
        public BindableField(string bindingName, Type dataType, bool isReadOnly, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            this.DataType = dataType;
            this.IsReadOnly = isReadOnly;
            this.SatelliteFields = satelliteFields;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="caption">Caption/description of the bound field. <b>Nullable</b>.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.</param>
        public BindableField(string bindingName, string caption, Type dataType, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            this.Caption = caption;
            this.DataType = dataType;
            this.SatelliteFields = satelliteFields;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="fieldCaptionProvider">Object that provides caption for the bound field. <b>Nullable</b>.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.</param>
        public BindableField(string bindingName, Type dataType, ICaptionProvider fieldCaptionProvider, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            if (fieldCaptionProvider != null)
                this.Caption = fieldCaptionProvider.GetFieldCaption(bindingName);
            this.DataType = dataType;
            this.SatelliteFields = satelliteFields;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="caption">Caption/description of the bound field. <b>Nullable</b>.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="isReadOnly">Indicates whether the contents of the field may be modified by binding engines.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.</param>
        public BindableField(string bindingName, string caption, Type dataType, bool isReadOnly, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            this.Caption = caption;
            this.DataType = dataType;
            this.IsReadOnly = isReadOnly;
            this.SatelliteFields = satelliteFields;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="fieldCaptionProvider">Object that provides caption for the bound field. <b>Nullable</b>.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="isReadOnly">Indicates whether the contents of the field may be modified by binding engines.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.</param>
        public BindableField(string bindingName, Type dataType, ICaptionProvider fieldCaptionProvider, bool isReadOnly, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            if (fieldCaptionProvider != null)
                this.Caption = fieldCaptionProvider.GetFieldCaption(bindingName);
            this.DataType = dataType;
            this.IsReadOnly = isReadOnly;
            this.SatelliteFields = satelliteFields;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="caption">Caption/description of the bound field. <b>Nullable</b>.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="isReadOnly">Indicates whether the contents of the field may be modified by binding engines.</param>
        /// <param name="codeList">The list of allowed values for the field. <b>Nullable</b>. 
        /// Typically used in combation with list controls.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field.</param>
        public BindableField(string bindingName, string caption, Type dataType, bool isReadOnly, ICodeList codeList, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            this.Caption = caption;
            this.DataType = dataType;
            this.IsReadOnly = isReadOnly;
            this.SatelliteFields = satelliteFields;
            this.CodeList = codeList;
        }

        /// <summary>
        /// Initializes a new instance of <b>BindableField</b> class.
        /// </summary>
        /// <param name="bindingName">Name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.</param>
        /// <param name="fieldCaptionProvider">Object that provides caption for the bound field. <b>Nullable</b>.</param>
        /// <param name="dataType">Type of the value stored in the property. Null is <b>not</b> allowed. 
        /// Primitive .NET types should be used whenever possible.</param>
        /// <param name="isReadOnly">Indicates whether the contents of the field may be modified by binding engines.</param>
        /// <param name="codeList">The list of allowed values for the field. <b>Nullable</b>. 
        /// Typically used in combation with list controls.</param>
        /// <param name="satelliteFields">Additional display fields that are uniquely identified by this field.</param>
        public BindableField(string bindingName, Type dataType, ICaptionProvider fieldCaptionProvider, bool isReadOnly, ICodeList codeList, params string[] satelliteFields)
        {
            this.BindingName = bindingName;
            if (fieldCaptionProvider != null)
                this.Caption = fieldCaptionProvider.GetFieldCaption(bindingName);
            this.DataType = dataType;
            this.IsReadOnly = isReadOnly;
            this.SatelliteFields = satelliteFields;
            this.CodeList = codeList;
        }

        #endregion

        #region Properties.

        /// <summary>
        /// Get the name of the property that is displayed and modified in binding engine. Null is <b>not</b> allowed.
        /// </summary>
        public string BindingName { get; private set; }

        /// <summary>
        /// Gets the type of the value stored in the property. Null is <b>not</b> allowed. 
        /// </summary>
        public Type DataType { get; private set; }

        /// <summary>
        /// Gets or sets the caption/description of the bound field. <b>Nullable</b>.
        /// </summary>
        public string Caption { get; set; }

        /// <summary>
        /// Gets or sets the value indicating whether the field is nullable. FieldBinding engines may use special 
        /// types/values to represent null-values, when the specified field <see cref="DataType"/> is not nullable.
        /// </summary>
        public bool IsNullable { get; set; }

        /// <summary>
        /// Gets or sets the value indicating whether the contents of the field may be modified by binding engines.
        /// </summary>
        public bool IsReadOnly { get; set; }

        /// <summary>
        /// Gets or sets the list of allowed values for the field. <b>Nullable</b>. Typically used in combation with list controls.
        /// </summary>
        public ICodeList CodeList { get; set; }

        /// <summary>
        /// Gets or sets additional display fields that are uniquely identified by this field. <b>Nullable</b>. 
        /// Typically used by lookup controls when the bound field represents a hidden key value.
        /// </summary>
        public string[] SatelliteFields { get; set; }

        /// <summary>
        /// Gets or sets the position of the field in the collection. 
        /// </summary>
        public int Ordinal { get; set; }

        /// <summary>
        /// Gets or sets the description of the bound field. <b>Nullable</b>.
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Gets or sets the value which indicates whether the field should be hidden from view in the user interface.
        /// </summary>
        public bool IsHidden { get; set; }

        #endregion
    }
}